/*
//  Copyright © 2014 Allen County Public Library.

  //        ACPL Mobile is free software: This program is distributed and you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.  ACPL Mobile is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, including without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ACPL Mobile. If not, see http://www.gnu.org/licenses/.
 * Author: James Harpe
 * 
 * Description: This service handles account notifications. 
 * 
 */

package us.in.lib.acpl.Mobile_ACPL.service.account;


import android.R;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v4.app.NotificationCompat;
import android.util.Xml;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import us.in.lib.acpl.Mobile_ACPL.AccountActivity;
import us.in.lib.acpl.Mobile_ACPL.patron.Checkout;
import us.in.lib.acpl.Mobile_ACPL.patron.Fine;
import us.in.lib.acpl.Mobile_ACPL.patron.Hold;
import us.in.lib.acpl.Mobile_ACPL.service.WakefulIntentService;
import us.in.lib.acpl.Mobile_ACPL.util.RestClient;
import us.in.lib.acpl.Mobile_ACPL.util.RestClient.RequestMethod;
import us.in.lib.acpl.Mobile_ACPL.ws.AccountInfoHandler;
import us.in.lib.acpl.Mobile_ACPL.ws.LoginHandler;
import us.in.lib.acpl.Mobile_ACPL.ws.SearchCatalogHandler;

public class AccountNotifyService extends WakefulIntentService {
	private final int OVERDUE_NOTIFY = 0;
	private final int DUE_SOON_NOTIFY = 1;
	private final int AVAILABLE_HOLD = 2;
	private final double MILLISECONDS_PER_DAY = 86400000.0;
	private final int DAYS_AHEAD = 3;
	private List<Hold> holds = new ArrayList<Hold>();
	private List<Checkout> checkouts = new ArrayList<Checkout>();
	private List<Fine> fines = new ArrayList<Fine>();
	private SharedPreferences prefs;

	public AccountNotifyService() {
		super("NotifyService");
	}

	@Override
	public void doWakefulWork(Intent intent) {
		System.out.print("starting service");
		prefs = this.getSharedPreferences("myPrefs",
				Context.MODE_WORLD_WRITEABLE);

		boolean loggedIn = prefs.getBoolean("loggedIn", false);
		String user = prefs.getString("user", null);
		boolean notifyDueDates = prefs.getBoolean("notifyDueDates",
				true);
		boolean notifyHolds = prefs.getBoolean("notifyHolds", true);

		boolean availableHolds = false;
		boolean upcomingDueDates = false;
		boolean overdueCheckouts = false;
		if (loggedIn && (notifyDueDates || notifyHolds)) {
			LoginHandler handler = new LoginHandler();
			handler.getNewSessionToken(prefs, this);
			lookupAccountInfo();

			if (notifyDueDates) {
				for (Checkout item : checkouts) {
					Date dueDate = item.getDueDate();
					String daysAhead = prefs.getString("daysAhead", "3");
					int daysInt = Integer.parseInt(daysAhead);
					Date date = new Date();
					double diff = (dueDate.getTime() - date.getTime())
							/ MILLISECONDS_PER_DAY;
					System.out.println(diff);
					if (diff < 0) {
						overdueCheckouts = true;
						break;
					} else if (diff < daysInt) {
						upcomingDueDates = true;
						break;
					}
				}
			}
			if (notifyHolds) {
				for (Hold hold : holds) {
					if (hold.isAvailable()) {
						availableHolds = true;
						break;
					}
				}
			}

			NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
			int icon = R.drawable.ic_dialog_info;

			long when = System.currentTimeMillis();

			if (availableHolds) {
				Intent notificationIntent = new Intent(this,
						AccountActivity.class);
				notificationIntent.putExtra("showHolds", true);
				PendingIntent contentIntent = PendingIntent.getActivity(this,
						0, notificationIntent, 0);
				Notification noti = new NotificationCompat.Builder(this)
						.setWhen(when).setContentTitle("Hold(s) available")
						.setContentText("Touch to view your account")
						.setTicker("Hold(s) Available").setAutoCancel(true)
						.setSmallIcon(icon).setContentIntent(contentIntent)
						.getNotification();

				mNotificationManager.notify(0, noti);

			}
			if (upcomingDueDates) {
				Intent notificationIntent = new Intent(this,
						AccountActivity.class);
				PendingIntent contentIntent = PendingIntent.getActivity(this,
						0, notificationIntent, 0);
				Notification noti = new NotificationCompat.Builder(this)
						.setWhen(when).setContentTitle("Upcoming Due Dates")
						.setContentText("Touch to view your account")
						.setTicker("Upcoming Due Dates").setAutoCancel(true)
						.setSmallIcon(icon).setContentIntent(contentIntent)
						.getNotification();

				mNotificationManager.notify(0, noti);
			}

			if (overdueCheckouts) {
				Intent notificationIntent = new Intent(this,
						AccountActivity.class);
				PendingIntent contentIntent = PendingIntent.getActivity(this,
						0, notificationIntent, 0);
				Notification noti = new NotificationCompat.Builder(this)
						.setWhen(when).setContentTitle("Item(s) Overdue")
						.setContentText("Touch to view your account")
						.setTicker("Item(s) Overdue").setAutoCancel(true)
						.setSmallIcon(icon).setContentIntent(contentIntent)
						.getNotification();

				mNotificationManager.notify(0, noti);
			}

		}

	}

	private void lookupAccountInfo() {
		String sessionToken = prefs.getString("sessionToken", null);
		RestClient client = new RestClient(AccountInfoHandler.ACCOUNT_URL);
		client.AddHeader("x-sirs-clientID", SearchCatalogHandler.CLIENT_ID);
		client.AddParam("sessionToken", sessionToken);
		client.AddParam("includePatronCirculationInfo", "true");
		client.AddParam("includePatronCheckoutInfo", "ALLEXCEPTLOST");
		client.AddParam("includePatronHoldInfo", "ACTIVE");
		client.AddParam("includeFeeInfo", "UNPAID_FEES");

		try {
			client.Execute(RequestMethod.POST);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		String response = client.getResponse();
		Hold currHold = new Hold();
		Checkout currCheckout = new Checkout();
		Fine currFine = new Fine();
		int currScope = 0;

		checkouts.clear();
		holds.clear();
		fines.clear();

		if (response == null) {
			return;
		}
		XmlPullParser parser = Xml.newPullParser();
		try {
			parser.setInput(new StringReader(response));

			int eventType = parser.next();
			while (eventType != XmlPullParser.END_DOCUMENT) {
				if (eventType == XmlPullParser.END_TAG) {
					String name = parser.getName();
					if (name.equalsIgnoreCase("patronCirculationInfo")) {

					}
					if (name.equalsIgnoreCase("patronCheckoutInfo")) {
						checkouts.add(currCheckout);
						currCheckout = new Checkout();
					}
					if (name.equalsIgnoreCase("patronHoldInfo")) {
						holds.add(currHold);
						currHold = new Hold();
					}
					if (name.equalsIgnoreCase("feeInfo")) {
						fines.add(currFine);
						currFine = new Fine();
					}
				}
				if (eventType == XmlPullParser.START_TAG) {
					String name = parser.getName();
					// Determine which type of object upcoming values belong
					// to.

					if (name.equalsIgnoreCase("patronCheckoutInfo")) {
						currScope = 0;
					}
					if (name.equalsIgnoreCase("patronHoldInfo")) {
						currScope = 1;
					}
					if (name.equalsIgnoreCase("feeInfo")) {
						currScope = 2;
					}
					if (name.equalsIgnoreCase("title")) {
						if (currScope == 0) {
							currCheckout.setTitle(parser.nextText());
						}
						if (currScope == 1) {
							currHold.setTitle(parser.nextText());
						}
						if (currScope == 2) {
							currFine.setTitle(parser.nextText());
						}
					}
					if (name.equalsIgnoreCase("author")) {
						if (currScope == 0) {
							currCheckout.setAuthor(parser.nextText());
						}
						if (currScope == 1) {
							currHold.setAuthor(parser.nextText());
						}
						if (currScope == 2) {
							currFine.setAuthor(parser.nextText());
						}
					}
					if (name.equalsIgnoreCase("itemID")) {
						if (currScope == 0) {
							currCheckout.setItemId(parser.nextText());
						}
						if (currScope == 1) {
							currHold.setItemId(parser.nextText());
						}
						if (currScope == 2) {
							currFine.setItemId(parser.nextText());
						}
					}
					if (name.equalsIgnoreCase("callNumber")) {
						if (currScope == 0) {
							currCheckout.setCallNumber(parser.nextText());
						}
						if (currScope == 1) {
							currHold.setCallNumber(parser.nextText());
						}
						if (currScope == 2) {
							currFine.setCallNumber(parser.nextText());
						}
					}
					if (name.equalsIgnoreCase("dueDate")) {
						currCheckout.setDueDate(parser.nextText());
					}
					if (name.equalsIgnoreCase("checkoutDate")) {
						currCheckout.setCheckoutDate(parser.nextText());
					}
					if (name.equalsIgnoreCase("renewals")) {
						currCheckout.setTimesRenewed(parser.nextText());
					}
					if (name.equalsIgnoreCase("overdue")) {
						currCheckout.setOverdue(Boolean.parseBoolean(parser
								.nextText()));
					}
					if (name.equalsIgnoreCase("holdKey")) {
						currHold.setHoldKey(parser.nextText());
					}
					if (name.equalsIgnoreCase("pickupLibraryID")) {
						currHold.setPickupLibrary(parser.nextText());
					}
					if (name.equalsIgnoreCase("placedDate")) {
						currHold.setPlacedDate(parser.nextText());
					}
					if (name.equalsIgnoreCase("available")) {
						currHold.setAvailable(Boolean.parseBoolean(parser
								.nextText()));
					}
					if (name.equalsIgnoreCase("queuePosition")) {
						currHold.setQueuePosition(parser.nextText());
					}
					if (name.equalsIgnoreCase("queueLength")) {
						currHold.setQueueLength(parser.nextText());
					}
					if (name.equalsIgnoreCase("billReasonID")) {
						currFine.setBillReason(parser.nextText());
					}
					if (name.equalsIgnoreCase("amountOutstanding")) {
						currFine.setAmountOutstanding(parser.nextText());
					}
					if (name.equalsIgnoreCase("dateBilled")) {
						currFine.setDateBilled(parser.nextText());
					}

				}
				eventType = parser.next();
			}

		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}